<script lang="ts" setup name="ndeReportReviewRecordAnalysis">
import { api } from '@/api';
import { urls } from '@/index';
import * as echarts from 'echarts';
import { dayjs } from 'element-plus';
import { useRequest } from 'vue-request';
import { useElementSize, useFullscreen } from '@vueuse/core';

let eChartForPrepare: echarts.ECharts;
let eChartForReview: echarts.ECharts;
let eChartForMethod: echarts.ECharts;
let eChartForCommentType: echarts.ECharts;

let prepareMap: HTMLDivElement;
let reviewMap: HTMLDivElement;
let methodMap: HTMLDivElement;
let commentTypeMap: HTMLDivElement;

const initDom = () => {
  prepareMap = document.getElementById('prepare') as HTMLDivElement;
  reviewMap = document.getElementById('review') as HTMLDivElement;
  methodMap = document.getElementById('method') as HTMLDivElement;
  commentTypeMap = document.getElementById('commentType') as HTMLDivElement;
};
const initEcharts = (color: 'dark' | 'light') => {
  if (color === 'dark') {
    eChartForPrepare = echarts.init(prepareMap, 'dark');
    eChartForReview = echarts.init(reviewMap, 'dark');
    eChartForMethod = echarts.init(methodMap, 'dark');
    eChartForCommentType = echarts.init(commentTypeMap, 'dark');
  } else {
    eChartForPrepare = echarts.init(prepareMap);
    eChartForReview = echarts.init(reviewMap);
    eChartForMethod = echarts.init(methodMap);
    eChartForCommentType = echarts.init(commentTypeMap);
  }
};

const updateEcharts = (color?: 'dark' | 'light') => {
  color = color == undefined ? colorMode.value : color;
  eChartForPrepare.dispose();
  eChartForReview.dispose();
  eChartForMethod.dispose();
  eChartForCommentType.dispose();
  if (color === 'dark') {
    eChartForPrepare = echarts.init(prepareMap, 'dark');
    eChartForReview = echarts.init(reviewMap, 'dark');
    eChartForMethod = echarts.init(methodMap, 'dark');
    eChartForCommentType = echarts.init(commentTypeMap, 'dark');
  } else {
    eChartForPrepare = echarts.init(prepareMap);
    eChartForReview = echarts.init(reviewMap);
    eChartForMethod = echarts.init(methodMap);
    eChartForCommentType = echarts.init(commentTypeMap);
  }
};

type EchartType = 'bar' | 'line' | 'pie';
type EchartTitle = 'prepare' | 'review' | 'method' | 'commentType';
const echartType = ref<EchartType>('bar');

const colorMode = ref<'dark' | 'light'>('light');

interface Data {
  reportReference: string;
  reviewTime: string;
  method: string;
  prepare: string;
  review: string;
  commentType: string;
}

const setOption = (echart: echarts.ECharts, option: echarts.EChartsOption) => {
  if (echart != undefined && echarts != null) {
    echart.clear();
  }
  echart.setOption(option);
};

const getDataList = async () => {
  const res = await api({
    url: urls.ndeReportReviewRecord + '/getReviewRecordExport'
  });
  if (res.data.status) {
    return res.data.body as Array<Data>;
  } else {
    ElMessage.error(res.data.msg);
  }
};

const { data: dataList } = useRequest(() => getDataList());

const dateRange = ref<string[]>([
  dayjs().subtract(1, 'month').format('YYYY-MM-DD'),
  dayjs().format('YYYY-MM-DD')
]);

// 根据单位和时间差设置时间范围
const setRange = (type: 'year' | 'month', num: number) => {
  const now = dayjs();
  dateRange.value[0] = now.subtract(num, type).format('YYYY-MM-DD');
  dateRange.value[1] = now.format('YYYY-MM-DD');
};

//根据时间范围缩小数据集
const dataListWithTime = computed<Array<Data>>(() => {
  const data = dataList.value;
  if (!data) return [];
  return data.filter(item => {
    const reviewTime = dayjs(item.reviewTime);
    return (
      reviewTime.isAfter(dayjs(dateRange.value[0]).subtract(1, 'day')) &&
      reviewTime.isBefore(dayjs(dateRange.value[1]).subtract(-1, 'day'))
    );
  });
});

const getText = (echartTitle: EchartTitle) => {
  switch (echartTitle) {
    case 'prepare':
      return '按编制人员';
    case 'review':
      return '按审核人员';
    case 'method':
      return '按检测方法';
    case 'commentType':
      return '按意见类型';
    default:
      return '';
  }
};

function generateObjectArray(arr1: Array<string>, arr2: Array<number>) {
  const result: Array<{ value: number; name: string }> = [];
  const length = Math.min(arr1.length, arr2.length);
  for (let i = 0; i < length; i++) {
    result.push({ value: arr2[i], name: arr1[i] });
  }
  return result;
}

const makeData = (
  echartTitle: EchartTitle,
  valueList: Array<Data>
): { dataX: Array<string>; dataY: Array<number> } => {
  if (valueList.length == 0) return { dataX: [], dataY: [] };
  else {
    const map = new Map<string, number>();
    valueList.forEach(item => {
      let key = '';
      switch (echartTitle) {
        case 'prepare':
          key = item.prepare;
          break;
        case 'review':
          key = item.review;
          break;
        case 'method':
          key = item.method;
          break;
        case 'commentType':
          key = item.commentType;
          break;
      }
      if (map.has(key)) {
        map.set(key, map.get(key)! + 1);
      } else {
        map.set(key, 1);
      }
    });
    const entries = Array.from(map.entries());
    entries.sort((a, b) => b[1] - a[1]);
    const sortedMap = new Map(entries);
    return { dataX: Array.from(sortedMap.keys()), dataY: Array.from(sortedMap.values()) };
  }
};
const makePieOption = (
  echartTitle: EchartTitle,
  valueList: Array<Data>,
  echartType: EchartType
): echarts.EChartsOption => {
  const { dataX, dataY } = makeData(echartTitle, valueList);
  return {
    title: {
      text: getText(echartTitle)
    },
    tooltip: {
      trigger: 'item'
    },
    series: [
      {
        type: echartType,
        data: generateObjectArray(dataX, dataY),
        emphasis: {
          itemStyle: {
            shadowBlur: 10,
            shadowOffsetX: 0,
            shadowColor: 'rgba(0, 0, 0, 0.5)'
          }
        }
      }
    ]
  };
};

const makeNonPieOption = (
  echartTitle: EchartTitle,
  valueList: Array<Data>,
  echartType: EchartType
): echarts.EChartsOption => {
  const { dataX, dataY } = makeData(echartTitle, valueList);
  return {
    title: {
      text: getText(echartTitle)
    },
    tooltip: {
      trigger: 'item'
    },
    xAxis: {
      type: 'category',
      data: dataX
    },
    yAxis: {
      type: 'value'
    },
    series: [
      {
        type: echartType,
        data: dataY
      }
    ]
  };
};
const makeOption = (
  valueList: Array<Data>,
  echartTitle: EchartTitle,
  echartType: EchartType
): echarts.EChartsOption => {
  return echartType == 'pie'
    ? makePieOption(echartTitle, valueList, echartType)
    : makeNonPieOption(echartTitle, valueList, echartType);
};

const draw = (valueList: Array<Data>, echartType: EchartType) => {
  setOption(eChartForPrepare, makeOption(valueList, 'prepare', echartType));
  setOption(eChartForReview, makeOption(valueList, 'review', echartType));
  setOption(eChartForMethod, makeOption(valueList, 'method', echartType));
  setOption(eChartForCommentType, makeOption(valueList, 'commentType', echartType));
};

onMounted(() => {
  initDom();
  initEcharts(colorMode.value);
});

watch(
  () => colorMode.value,
  value => {
    updateEcharts(value);
    draw(dataListWithTime.value, echartType.value);
  }
);

watch(
  () => [echartType.value, dataListWithTime.value],
  async value => {
    const dataX = value[0] as EchartType;
    const dataY = value[1] as Array<Data>;
    draw(dataY, dataX);
  }
);
const el = useTemplateRef<HTMLDivElement>('el');
const { width, height } = useElementSize(el);
watch(
  () => [width.value, height.value],
  value => {
    eChartForPrepare.resize();
    eChartForReview.resize();
    eChartForMethod.resize();
    eChartForCommentType.resize();
  }
);

const { isFullscreen, toggle } = useFullscreen(el);
</script>
<template>
  <div class="container" ref="el">
    <div class="header">
      <el-row>
        <el-col :span="7">
          <el-button type="primary" plain @click="setRange('year', 3)">最近3年</el-button>
          <!-- <el-button type="success" plain @click="setRange('year', 1)">最近1年</el-button> -->
          <el-button type="info" plain @click="setRange('month', 6)">最近6月</el-button>
          <el-button type="warning" plain @click="setRange('month', 3)">最近3月</el-button>
          <el-button type="danger" plain @click="setRange('month', 1)">最近1月</el-button>
          <el-button type="info" plain @click="toggle">
            {{ isFullscreen ? '退出全屏' : '进入全屏' }}
          </el-button>
        </el-col>
        <el-col :span="7">
          日期区间：
          <el-date-picker v-model="dateRange" type="daterange" range-separator="到" start-placeholder="开始日期"
            end-placeholder="结束日期" />
        </el-col>
        <el-col :span="6">
          <el-radio-group v-model="echartType">
            <el-radio value="bar" label="柱状图" border />
            <el-radio value="line" label="折线图" border />
            <el-radio value="pie" label="饼状图" border />
          </el-radio-group>
        </el-col>
        <el-col :span="4">
          <el-radio-group v-model="colorMode">
            <el-radio value="light" label="浅色" border />
            <el-radio value="dark" label="深色" border />
          </el-radio-group>
        </el-col>
      </el-row>
    </div>
    <div class="body" ref="el">
      <div id="prepare"></div>
      <div id="review"></div>
      <div id="method"></div>
      <div id="commentType"></div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.container {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;

  .header {
    height: 60px;
    line-height: 59px;
    padding-left: 5px;
    display: flex;
    align-items: center;

    .el-row {
      width: 100%;
      display: flex;
    }
  }

  .body {
    padding: 5px;
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    justify-content: space-around;

    >* {
      width: calc(50% - 2.5px);
      height: calc(50% - 2.5px);
      border: 1px dotted rgb(212, 108, 23);
      border-radius: 5px;
    }
  }
}

.toggle {
  display: flex;
  align-items: center;
  justify-content: right;
  padding-right: 10px;
}
</style>
